package com.eastfair.projectcore.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.eastfair.auth.entity.UserAccount;
import com.eastfair.constant.BusinessConstant;
import com.eastfair.core.base.R;
import com.eastfair.core.context.ContextUtil;
import com.eastfair.core.exception.code.ExceptionCode;
import com.eastfair.core.snowflake.DefaultUidGenerator;
import com.eastfair.projectcore.dao.AppMenuMapper;
import com.eastfair.projectcore.dto.AppMenuDTO;
import com.eastfair.projectcore.dto.AppMenuSaveDTO;
import com.eastfair.projectcore.dto.AppMenuUpdateDTO;
import com.eastfair.projectcore.dto.MenuDTO;
import com.eastfair.projectcore.entity.AppMenu;
import com.eastfair.projectcore.entity.Menu;
import com.eastfair.projectcore.enumeration.AppMenuMenuTypeEnum;
import com.eastfair.projectcore.enumeration.MenuMenuTypeEnum;
import com.eastfair.projectcore.service.AppMenuService;
import com.eastfair.boot.service.SuperServiceImpl;

import com.eastfair.projectcore.vo.AppMenuVO;
import com.eastfair.projectcore.vo.MenuVO;
import com.eastfair.uid.model.SelfUidDto;
import com.eastfair.uid.service.SelfUidService;
import com.eastfair.util.CodeUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.extension.toolkit.SqlHelper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;

import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 业务实现类
 * 前端菜单（之所以分开是因为避免指定上级菜单出错）
 * </p>
 *
 * @author ligang
 * @date 2021-10-28
 */
@Slf4j
@Service
public class AppMenuServiceImpl extends SuperServiceImpl<AppMenuMapper, AppMenu> implements AppMenuService {
//    @Autowired
//    SelfUidService selfUidService;

    /**
     * 处理新增相关处理
     *
     * @param appMenu 实体
     * @return 是否成功
     */
    @Override
    protected R<Boolean> handlerSave(AppMenu appMenu) {
        //雪花ID,不需要分库分表
//        SelfUidDto selfUidDto = new SelfUidDto();
//        appMenu.setId(selfUidService.getUid(selfUidDto));
        appMenu.setId(DefaultUidGenerator.getUid(0L));

        if (appMenu.getParentId() == null) {
            //组织顶级为0
            appMenu.setParentId(BusinessConstant.parentId);
        }
        //code 码
        if (StringUtils.isBlank(appMenu.getCode())) {
            appMenu.setCode(queryCode(appMenu));
        }
        if (appMenu.getSequence() == null) {
            //排序
            appMenu.setSequence(1);
            if (appMenu.getParentId() != null) {
                appMenu.setSequence(querySort(appMenu.getParentId()));
            }
        }
        return R.successDef();
    }


    @Override
    public R del(Long id) {
        AppMenu appMenu = getById(id);
        if (appMenu != null) {
            //同时删除旗下子节点
            delChild(appMenu);
            appMenu.setIsDeleted(BusinessConstant.DELETE_YES);
            updateById(appMenu);
        }
        return R.successDef();
    }

    @Override
    public R delChild(AppMenu appMenu) {
        if (appMenu != null) {
            String code = appMenu.getCode();
            List<AppMenu> menuList = queryAllOfCode(Arrays.asList(code + ","), null, null);
            if (menuList != null && !menuList.isEmpty()) {
                for (AppMenu appMenu1 : menuList) {
                    appMenu1.setIsDeleted(BusinessConstant.DELETE_YES);
                    updateById(appMenu1);
                }
            }
        }
        return R.successDef();
    }

    @Override
    public int querySort(Long parentId) {
        if (parentId == 0) {
            return 1;
        }
        List<AppMenu> appMenuList = queryEntityOfParentId(parentId);
        if (appMenuList != null && !appMenuList.isEmpty()) {
            int max = appMenuList.stream().mapToInt(s -> s.getSequence()).max().getAsInt();
            return max + 1;
        }
        return 1;
    }

    @Override
    public String queryCode(AppMenu appMenu) {
        String code = nonredundantCode();
        if (appMenu.getParentId() != 0) {
            AppMenu appMenu1 = getById(appMenu.getParentId());
            if (appMenu1 != null) {
                code = appMenu1.getCode() + "," + code;
            }
        }
        return code;
    }

    /**
     * 获取不重复的code
     *
     * @return
     */
    public String nonredundantCode() {
        String code = CodeUtils.randomCode(6);
        //是否重复
        int num = queryCodeSize(code);
        if (num > 0) {
            nonredundantCode();
        }
        return code;
    }


    @Override
    public void sortTop(Long id) {
        AppMenu appMenu = getById(id);
        if (appMenu.getParentId() == 0) {
            return;
        }
        appMenu.setSequence(1);
        updateById(appMenu);
        List<AppMenu> appMenuList = queryEntityOfParentId(appMenu.getParentId());
        int num = 2;
        if (appMenuList != null && !appMenuList.isEmpty()) {
            for (AppMenu appMenu1 : appMenuList) {
                if (appMenu1.getId().equals(id)) {
                    appMenu1.setSequence(num++);
                    updateById(appMenu1);
                }
            }
        }
    }

    @Override
    public void initSort(Long parentId) {
        List<AppMenu> appMenuList = queryEntityOfParentId(parentId);
        if (appMenuList != null && !appMenuList.isEmpty()) {
            int num = 1;
            for (AppMenu appMenu : appMenuList) {
                appMenu.setSequence(num++);
                updateById(appMenu);
            }
        }
    }

    @Override
    public List<AppMenu> queryAllOfCode(List<String> rightCodes, List<String> leftCodes, AppMenuDTO appMenuDTO) {
        QueryWrapper<AppMenu> queryWrapper = new QueryWrapper<>();
        if (rightCodes != null && !rightCodes.isEmpty()) {
//            queryWrapper.lambda().likeRight(Menu::getCode, rightCode);
            queryWrapper.and(wrapper -> {
                for (int i = 0; i < rightCodes.size(); i++) {
                    wrapper.likeRight("code", rightCodes.get(i));
                    if (i < (rightCodes.size() - 1)) {
                        wrapper.or();
                    }
                }
            });
        }
        if (leftCodes != null && !leftCodes.isEmpty()) {
//            queryWrapper.lambda().likeLeft(Menu::getCode, leftCode);
            queryWrapper.and(wrapper -> {
                for (int i = 0; i < leftCodes.size(); i++) {
                    wrapper.likeLeft("code", leftCodes.get(i));
                    if (i < (leftCodes.size() - 1)) {
                        wrapper.or();
                    }
                }
            });
        }
        queryWrapper.lambda().eq(AppMenu::getIsDeleted, BusinessConstant.DELETE_NO);
        //是否显示
        queryWrapper.lambda().eq(AppMenu::getIsShow, BusinessConstant.YES);
        //是否生效
        queryWrapper.lambda().eq(AppMenu::getIsEnabled, BusinessConstant.YES);
        //排序查询
        queryWrapper.orderByAsc("sequence");
        List<AppMenu> appMenuList = list(queryWrapper);
        return appMenuList;
    }

    @Override
    public int queryCodeSize(String code) {
        QueryWrapper<AppMenu> queryWrapper = new QueryWrapper<>();
        if (StringUtils.isNotBlank(code)) {
            queryWrapper.lambda().eq(AppMenu::getCode, code);
        }
        queryWrapper.lambda().eq(AppMenu::getIsDeleted, BusinessConstant.DELETE_NO);
        //排序查询
        queryWrapper.orderByAsc("sequence");
        return count(queryWrapper);
    }

    @Override
    public AppMenuVO loadTree(String parentCode, List<AppMenuVO> appMenuVOList) {
        List<AppMenuVO> tree = new ArrayList<>();
        for (AppMenuVO appMenuVO : appMenuVOList) {
            //找到根节点
            if (appMenuVO.getCode().equals(parentCode)) {
                tree.add(findChildren(appMenuVO, appMenuVOList));
                break;
            }
        }
        return tree.get(0);
    }

    /**
     * 查找menuVo的子节点
     *
     * @param appMenuVO 根节点
     * @param list
     * @return
     */
    private AppMenuVO findChildren(AppMenuVO appMenuVO, List<AppMenuVO> list) {
        List<AppMenuVO> children = new ArrayList<>();
        for (AppMenuVO node : list) {
            if (node.getParentId().equals(appMenuVO.getId())) {
                //递归调用
                children.add(findChildren(node, list));
            }
        }
        appMenuVO.setChildVoList(children);
        return appMenuVO;
    }


    @Override
    public R<AppMenu> createMenu(AppMenuSaveDTO appMenuSaveDTO) {
        AppMenu appMenu = new AppMenu();
        BeanUtils.copyProperties(appMenuSaveDTO, appMenu);
        //校验数据合法性
        R r = verifyMenu(appMenu);
        if (R.SUCCESS_CODE != r.getCode()) {
            return r;
        }
        //新增
        save(appMenu);
        return R.success(appMenu);
    }

    @Override
    public R<AppMenu> updateMenu(AppMenuUpdateDTO appMenuUpdateDTO) {
        AppMenu appMenu = new AppMenu();
        BeanUtils.copyProperties(appMenuUpdateDTO, appMenu);
        //校验数据合法性
        R r = verifyMenu(appMenu);
        if (R.SUCCESS_CODE != r.getCode()) {
            return r;
        }
        //修改
        updateById(appMenu);
        return R.success(appMenu);
    }

    /**
     * 校验参数是否正确
     *
     * @param appMenu
     * @return
     */
    public R verifyMenu(AppMenu appMenu) {
        //校验判断：1必须有上级菜单  2 必须有菜单类型 3必须有菜单名称
        if (appMenu.getParentId() == null || appMenu.getMenuType() == null || StringUtils.isBlank(appMenu.getName())) {
            return R.fail(ExceptionCode.MENU_PARAM_ERROR);
        }
        //如果是外链，必须有外链地址
        if (BusinessConstant.YES == appMenu.getIsOutLink() && StringUtils.isBlank(appMenu.getLink())) {
            return R.fail(ExceptionCode.MENU_PARAM_ERROR);
        }
        if (MenuMenuTypeEnum.CATALOG.getCode().equals(appMenu.getMenuType().getCode())) {
            //目录
        } else if (MenuMenuTypeEnum.MENU.getCode().equals(appMenu.getMenuType().getCode())) {
            //菜单
        } else if (MenuMenuTypeEnum.BUTTON.getCode().equals(appMenu.getMenuType().getCode())) {
            //按钮 必须有权限字符
            if (StringUtils.isBlank(appMenu.getPermission())) {
                return R.fail(ExceptionCode.MENU_PARAM_ERROR);
            }
        }
        return R.success();
    }

    @Override
    public List<AppMenu> queryEntityOfParentId(Long parentId) {
        QueryWrapper<AppMenu> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(AppMenu::getParentId, parentId);
        queryWrapper.lambda().eq(AppMenu::getIsDeleted, BusinessConstant.DELETE_NO);
        //排序查询
        queryWrapper.orderByAsc("sequence");
        return list(queryWrapper);
    }

    @Override
    public AppMenuVO findAllById(Long id) {
        if (id == null) {
            //查顶级菜单
            QueryWrapper<AppMenu> queryWrapper = new QueryWrapper<>();
            queryWrapper.lambda().eq(AppMenu::getIsDeleted, BusinessConstant.DELETE_NO);
            queryWrapper.lambda().eq(AppMenu::getParentId, BusinessConstant.parentId);
            //查询用户
            List<AppMenu> menuList = list(queryWrapper);
            if (menuList != null && !menuList.isEmpty()) {
                id = menuList.get(0).getId();
            }
        }
        AppMenu appMenu = getById(id);
        if (appMenu != null) {
            String code = appMenu.getCode();
            List<AppMenu> childMenuList = queryAllOfCode(Arrays.asList(code), null, null);
            if (childMenuList != null && !childMenuList.isEmpty()) {
                return loadTree(code, doToVos(childMenuList));
            }
        }
        return null;
    }

    @Override
    public AppMenuVO findAllByIdNoButton(Long id) {
        AppMenu appMenu = getById(id);
        if (appMenu != null) {
            String code = appMenu.getCode();
            //只查询菜单和目录
            List<AppMenu> childAppMenuList = queryAllOfCode(Arrays.asList(code), null, null);
            //查询按钮级别菜单
            List<AppMenu> buttonMenuList = childAppMenuList.stream().filter(s -> AppMenuMenuTypeEnum.BUTTON.getCode().equals(s.getMenuType().getCode())).collect(Collectors.toList());
            //过滤掉按钮级别菜单
            childAppMenuList = childAppMenuList.stream().filter(s -> !AppMenuMenuTypeEnum.BUTTON.getCode().equals(s.getMenuType().getCode())).collect(Collectors.toList());
            if (childAppMenuList != null && !childAppMenuList.isEmpty()) {

                AppMenuVO appMenuVO = loadTree(code, doToVos(childAppMenuList));
//                if(buttonMenuList !=null && !buttonMenuList.isEmpty()){
//                    appMenuVO.setButtonPermissionList(buttonMenuList.stream().map(AppMenu::getPermission).collect(Collectors.toList()));
//                }
                return appMenuVO;
            }
        }
        return null;
    }

    public List<AppMenuVO> doToVos(List<AppMenu> appMenuList) {
        if (appMenuList == null || appMenuList.isEmpty()) {
            return null;
        }
        List<AppMenuVO> result = new ArrayList<>();
        for (AppMenu appMenu : appMenuList) {
            result.add(doToVo(appMenu));
        }
        return result;
    }

    public AppMenuVO doToVo(AppMenu appMenu) {
        AppMenuVO appMenuVO = new AppMenuVO();
        BeanUtils.copyProperties(appMenu, appMenuVO);
        appMenuVO.setId(appMenu.getId());
        //菜单层数
        appMenuVO.setLevel(appMenu.getCode().split(",").length);
        return appMenuVO;
    }


    @Override
    public List<AppMenuVO> findAllByChildId(List<Long> childIds) {
        List<AppMenuVO> result = new ArrayList<>();
        if (childIds != null && !childIds.isEmpty()) {
            List<AppMenu> appMenuList = listByIds(childIds);
            if (appMenuList != null && !appMenuList.isEmpty()) {
                //过滤父级菜单信息
                Set<String> parentMenuSet = new HashSet<>();
                List<String> childCodes = appMenuList.stream().map(AppMenu::getCode).collect(Collectors.toList());
                for (AppMenu appMenu : appMenuList) {
                    if (appMenu.getCode().indexOf(",") > -1) {
                        parentMenuSet.add(appMenu.getCode().substring(0, appMenu.getCode().indexOf(",")));
                    } else {
                        parentMenuSet.add(appMenu.getCode());
                    }

                }
                List<AppMenu> childMenuList = queryAllOfCode(new ArrayList<>(parentMenuSet), null, null);
                if (childMenuList != null && !childMenuList.isEmpty()) {
                    //过滤非节点菜单信息
                    childMenuList = childMenuList.stream().filter(p -> {
                        for (String str : childCodes) {
                            if (str.indexOf(p.getCode()) > -1) {
                                return true;
                            }
                        }
                        return false;
                    }).collect(Collectors.toList());
                    //组装菜单信息
                    for (String code : parentMenuSet) {
                        AppMenuVO menuVo = loadTree(code, doToVos(childMenuList));
                        if (menuVo != null) {
                            result.add(menuVo);
                        }
                    }
                }
            }
        }
        return result;
    }

    @Override
    public List<String> findPermissionAllByChildId(List<Long> childIds) {
        List<AppMenuVO> result = new ArrayList<>();
        if (childIds != null && !childIds.isEmpty()) {
            List<AppMenu> appMenuList = listByIds(childIds);
            if (appMenuList != null && !appMenuList.isEmpty()) {
                return appMenuList.stream().filter(s -> StringUtils.isNotBlank(s.getPermission())).map(AppMenu::getPermission).collect(Collectors.toList());

            }
        }
        return null;
    }
}
